import pyautogui
import time
import logging
# import sys
# import signal
import keyboard  # 用于检测按键
# from pynput import mouse
# import threading
# from PyQt5.QtGui import QIcon, QMovie
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, \
    QSpacerItem, QSizePolicy, QTextEdit
from PyQt5.QtCore import Qt, QTimer, QPoint, QThread, pyqtSignal
from PyQt5.QtGui import QMouseEvent

# import inspect
from functools import wraps

# 默认点击次数
Default_Clicks = 100

WindowOpacity_Hide = 0.2
WindowOpacity_Show = 1
Click_Delay = 0.01

_logger = logging.getLogger(__name__)
_logger.setLevel(logging.INFO)

GoOnFlag = True


class AutoClickThread(QThread):
    # 定义一个信号，用于从工作线程发送结果到主线程
    AutoClickThreadSignal = pyqtSignal(str)

    def __init__(self, click_window=None):
        super(AutoClickThread, self).__init__()
        self.click_window = click_window
        self.click_count = 0

    def set_click_count(self, count=0):
        self.click_count = count

    def qthread_auto_click(self):
        _logger.error('开始自动点击')
        while self.click_count < int(self.click_window.clicks_input.text() or Default_Clicks) and GoOnFlag:
            self.click_count += 1
            pyautogui.click(self.click_window.click_position_x, self.click_window.click_position_y)
            if self.click_count % 20 == 0:
                print(f'已经点击{self.click_count}')
            time.sleep(Click_Delay)

    def run(self):
        # 执行自动点击操作
        self.qthread_auto_click()
        self.AutoClickThreadSignal.emit('Auto Click')

    ...


# 连点窗口
class ClickWindow(QWidget):
    def __init__(self):
        super(ClickWindow, self).__init__()
        self.clicks_input = None
        self.note_label = None
        self.note_label_xy = None
        self.position_button = None
        self.start_button = None
        self.click_position_x = None
        self.click_position_y = None
        self.click_count = 0
        self.window_opacity = WindowOpacity_Show

        # 定时器
        self.auto_click_timer = QTimer()

        # 初始化界面
        self.initUI()

        # 自动点击动作-线程
        self.AutoClickThread = AutoClickThread(self)

        ...

    ...

    def initUI(self):
        self.setWindowTitle("自动点击器")
        self.setGeometry(300, 100, 300, 300)
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)  # 设置窗口始终保持在最前面
        # self.setWindowIcon(QIcon('./pet_images/cheems/icon.png'))  # 设置窗口图标

        # 创建一个布局
        layout = QVBoxLayout()

        # 输入框
        self.clicks_input = QLineEdit(self)
        self.clicks_input.setPlaceholderText(f'点击次数，默认{Default_Clicks}')
        # self.clicks_input.setFocusPolicy(Qt.NoFocus)  # 设置焦点策略为无焦点
        # self.clicks_input.setText('100')
        layout.addWidget(self.clicks_input)

        # 提示文字
        self.note_label = QLabel('按Q或者Esc退出自动点击', self)
        layout.addWidget(self.note_label)

        # 显示xy
        self.note_label_xy = QTextEdit('', self)
        self.note_label_xy.setReadOnly(True)
        self.note_label_xy.setFixedSize(200, 50)
        layout.addWidget(self.note_label_xy)

        # 水平布局
        button_layout = QHBoxLayout()

        # 选择点击位置按钮
        self.position_button = QPushButton('选择点击位置', self)
        self.position_button.clicked.connect(self.hide_and_wait_for_click)
        button_layout.addWidget(self.position_button)

        # 开始按钮
        self.start_button = QPushButton('开始', self)
        self.start_button.clicked.connect(self.start_auto_click)
        self.start_button.hide()
        button_layout.addWidget(self.start_button)

        layout.addLayout(button_layout)

        # 设置焦点顺序
        self.position_button.setFocus()
        self.setTabOrder(self.position_button, self.clicks_input)
        # self.setTabOrder(self.clicks_input, self.position_button)

        self.setLayout(layout)
        self.show()
        ...

    # 点击后隐藏
    def hide_and_wait_for_click(self):
        self.note_label_xy.setText('')
        self.hide_windows_self()  # 隐藏窗口
        self.grabMouse()  # 捕获鼠标事件

    # 鼠标点击监控，窗口外不能被监控到
    def mousePressEvent(self, event: QMouseEvent) -> None:

        # 隐藏时点击鼠标
        if self.window_opacity == WindowOpacity_Hide:
            self.show_windows_self()  # 展示窗口
            self.releaseMouse()  # 释放鼠标事件

            self.click_position_x, self.click_position_y = event.globalPos().x(), event.globalPos().y()
            self.note_label_xy.setText(f'点击位置: {self.click_position_x, self.click_position_y}')
            self.position_button.setText(f'重新选择点击位置')

            # 展示“开始按钮”
            self.start_button.show()

        else:
            return

    # 点击后，定时启动
    def start_auto_click(self):
        # 设置定时5秒后开始自动点击
        self.auto_click_timer.singleShot(1000, self.auto_click)

    # 自动点击
    def auto_click(self):
        global GoOnFlag

        # 开始监听键盘事件
        GoOnFlag = True
        keyboard.hook(on_keyboard_event)

        self.AutoClickThread.AutoClickThreadSignal.connect(self.stop_auto_click)
        self.AutoClickThread.start()
        ...

    def stop_auto_click(self):
        # self.auto_click_timer.stop()
        self.click_count = 0
        print('停止..........\n')
        # 终止线程
        self.AutoClickThread.set_click_count()
        self.AutoClickThread.terminate()
        # 等待线程结束
        self.AutoClickThread.wait()
        # self.AutoClickThread.quit()

        # 断开connect，避免重复连接而导致的多次调用
        self.AutoClickThread.AutoClickThreadSignal.disconnect(self.stop_auto_click)

        # 停止监听键盘事件
        keyboard.unhook(on_keyboard_event)

    def keyPressEvent(self, event) -> None:
        key = event.key()
        if key in [Qt.Key_Q, Qt.Key_Escape]:
            self.stop_auto_click()

    # 显示
    def show_windows_self(self):
        self._set_window_opacity(WindowOpacity_Show)

    # 隐藏
    def hide_windows_self(self):
        self._set_window_opacity(WindowOpacity_Hide)

    def _set_window_opacity(self, value):
        self.window_opacity = value
        self.setWindowOpacity(value)

    ...


# 设置安全退出标志
exit_flag = False


def on_keyboard_event(event):
    global exit_flag
    global GoOnFlag
    if (event.name == 'c' and event.event_type == 'down' and keyboard.is_pressed('ctrl')) \
            or (event.name == 'esc' and event.event_type == 'down') \
            or (event.name == 'q' and event.event_type == 'down'):
        # print("程序正在退出...")
        exit_flag = True
        GoOnFlag = False
        return False  # 停止监听键盘事件


def qy_main():
    app = QApplication(sys.argv)
    click_gui = ClickWindow()
    sys.exit(app.exec_())
    ...


if __name__ == "__main__":
    qy_main()
